#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkCameraOrientationWidget.h>
#include <vtkDataSetMapper.h>
#include <vtkInteractorStyleSwitch.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSpatioTemporalHarmonicsSource.h>

int main(int, char*[])
{

  vtkNew<vtkNamedColors> colors;

  // Create the source.
  const int MAX_EXTENT = 10;
  vtkNew<vtkSpatioTemporalHarmonicsSource> source;
  source->SetWholeExtent(-MAX_EXTENT, MAX_EXTENT,
                         -MAX_EXTENT, MAX_EXTENT,
                         -MAX_EXTENT, MAX_EXTENT);

  source->ClearHarmonics();
  source->AddHarmonic(1.0, 1.0, 1.0, 0.0, 0.0, 0.0);
  source->AddHarmonic(2.0, 1.0, 0.0, 1.0, 0.0, 0.0);
  source->AddHarmonic(4.0, 1.0, 0.0, 0.0, 1.0, 0.0);

  source->ClearTimeStepValues();
  source->AddTimeStepValue(0.0);
  source->AddTimeStepValue(1.0);
  source->AddTimeStepValue(2.0);

  // Create the mapper and actor.
  vtkNew<vtkDataSetMapper> mapper;
  mapper->SetInputConnection(source->GetOutputPort());
  mapper->SetScalarRange(-6.0, 6.0);

  vtkNew<vtkActor> actor;
  actor->SetMapper(mapper);

  // Create a renderer, render window, and interactor.
  vtkNew<vtkRenderer> ren;
  ren->SetBackground(colors->GetColor3d("Gray").GetData());
  vtkNew<vtkRenderWindow> renWin;
  renWin->SetWindowName("SpatioTemporalHarmonicsSource");
  renWin->SetSize(600, 600);
  renWin->AddRenderer(ren);
  vtkNew<vtkRenderWindowInteractor> iRen;
  iRen->SetRenderWindow(renWin);
  auto is = vtkInteractorStyleSwitch::SafeDownCast(iRen->GetInteractorStyle());
  if (is)
  {
    is->SetCurrentStyleToTrackballCamera();
  }

  ren->ResetCamera();
  ren->GetActiveCamera()->SetPosition(50.0, 40.0, 30.0);
  ren->GetActiveCamera()->SetFocalPoint(0.0, 0.0, 0.0);
  ren->ResetCameraClippingRange();

  // Add the actor, render and interact.
  ren->AddActor(actor);
  renWin->Render();

  vtkNew<vtkCameraOrientationWidget> cow;
  cow->SetParentRenderer(ren);
  // Enable the widget.
  cow->On();

  iRen->Start();

  return EXIT_SUCCESS;
}
